/*
 * Licensed to Nanjing RedOrange Co. ltd (RedOrange) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * RedOrange licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package redora.generator;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import redora.generator.Template.Destination;
import redora.generator.Template.DestinationType;
import redora.generator.Template.Input;
import redora.generator.Template.Type;

public class TemplateHandler {

	private Document doc;
	
	public TemplateHandler() throws SAXException, ParserConfigurationException, IOException {
		doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(findFile("templates.xml"));
	}	
	
	/**
	 * Finds the file. First it will try the local src/main/resources dir. Then it will try the
	 * resources dir in the p-generator project. Finally it will will try the classpath in /templates
	 * @param fileName filename without path.
	 * @return Returns an Inputstream or a FileNotFoundexception.
	 */
	public InputStream findFile(String fileName) throws FileNotFoundException {
		File file = new File("src" + File.separator + "main" + File.separator + "resources" + File.separator + fileName);
		if (file.exists()) {
			System.out.println("Found " + fileName + " local");
			return new FileInputStream(file);
		} else {
			file = new File("p-generator" + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + fileName);
			if (file.exists()) {
				System.out.println("Found " + fileName + " in Redora development (p-generator)");
				return new FileInputStream(file);
			} else {
				InputStream in = getClass().getResourceAsStream("/templates/" + fileName); 
				if (in != null) {
					System.out.println("Found " + fileName + " in custom classpath (/templates)");
					return in;
				}
			}
		}
		System.out.println("Found " + fileName + " in classpath");
		return getClass().getResourceAsStream("/" + fileName);
	}
	
	/** @return List of all the templates that use given input. */
	public List<Template> byInput(Input input) throws XPathExpressionException {
		List<Template> retVal = new LinkedList<Template>();
	
		XPathFactory factory = XPathFactory.newInstance();
		XPath xpath = factory.newXPath();
		NodeList templateNodes = (NodeList) xpath.evaluate("//template[@input='" + input + "']", doc,
				XPathConstants.NODESET);
		for (int i = 0; i < templateNodes.getLength(); i++) {
			retVal.add(from(templateNodes.item(i)));
		}
	
		return retVal;
	}

	/** Will get a Template object form the templates.xml document. */
	public static Template from(Node node) {
		Template retVal = new Template(
				node.getAttributes().getNamedItem("name").getNodeValue()
				, Type.valueOf(node.getAttributes().getNamedItem("type").getNodeValue())
				, Destination.valueOf(node.getAttributes().getNamedItem("destination").getNodeValue())
				);
		if (node.getAttributes().getNamedItem("templateFileName") != null) {
			retVal.setTemplateFileName(node.getAttributes().getNamedItem("templateFileName").getNodeValue());
		}
		if (node.getAttributes().getNamedItem("ignoreProjects") != null) {
			retVal.setIgnoreProjects(node.getAttributes().getNamedItem("ignoreProjects").getNodeValue());
		}
		if (node.getAttributes().getNamedItem("destinationType") != null) {
			retVal.setDestinationType(DestinationType.valueOf(node.getAttributes().getNamedItem("destinationType").getNodeValue()));
		}
		if (node.getAttributes().getNamedItem("input") != null) {
			retVal.setInput(Input.valueOf(node.getAttributes().getNamedItem("input").getNodeValue()));
		}
		if (node.getAttributes().getNamedItem("package") != null) {
			retVal.setPackageSuffix(node.getAttributes().getNamedItem("package").getNodeValue());
		}
		if (node.getAttributes().getNamedItem("path") != null) {
			retVal.setPath(node.getAttributes().getNamedItem("path").getNodeValue());
		}
	
		return retVal;
	}
}
